import os
import struct
import hashlib
from typing import Dict, List
from dataclasses import dataclass

@dataclass
class FileInfo:
    """文件信息类"""
    name: str          # 文件名
    offset: int        # 文件在包中的偏移
    size: int          # 文件大小
    checksum: str      # 文件校验和

class ResourcePacker:
    """资源打包工具"""
    # 文件头魔数 (DTWS)
    MAGIC = 0x44545753
    # 当前版本
    VERSION = 1
    
    def __init__(self):
        self.files: List[FileInfo] = []
    
    def _calculate_checksum(self, data: bytes) -> str:
        """计算数据的校验和"""
        return hashlib.sha256(data).hexdigest()
    
    def pack_directory(self, src_dir: str, output_file: str):
        """打包目录"""
        # 收集文件信息
        file_data: Dict[str, bytes] = {}
        base_path = os.path.abspath(src_dir)
        
        # 遍历目录收集文件
        for root, _, files in os.walk(src_dir):
            for file in files:
                full_path = os.path.join(root, file)
                rel_path = os.path.relpath(full_path, base_path)
                
                # 读取文件数据
                with open(full_path, 'rb') as f:
                    data = f.read()
                    file_data[rel_path] = data
        
        # 开始写入打包文件
        with open(output_file, 'wb') as f:
            # 1. 写入文件头
            f.write(struct.pack('<I', self.MAGIC))      # 魔数
            f.write(struct.pack('<I', self.VERSION))    # 版本号
            f.write(struct.pack('<I', len(file_data)))  # 文件数量
            
            # 预留校验和位置
            checksum_pos = f.tell()
            f.write(b'\x00' * 32)
            
            # 2. 预留索引表空间
            index_size = sum(4 + len(name) + 8 + 8 + 32 for name in file_data.keys())
            index_pos = f.tell()
            f.write(b'\x00' * index_size)
            
            # 3. 写入文件数据
            current_offset = f.tell()
            index_data = []
            
            for name, data in file_data.items():
                file_info = FileInfo(
                    name=name,
                    offset=current_offset,
                    size=len(data),
                    checksum=self._calculate_checksum(data)
                )
                index_data.append(file_info)
                
                # 写入文件数据
                f.write(data)
                current_offset = f.tell()
            
            # 4. 写入索引表
            f.seek(index_pos)
            for info in index_data:
                # 写入文件名
                f.write(struct.pack('<I', len(info.name)))
                f.write(info.name.encode('utf-8'))
                # 写入偏移和大小
                f.write(struct.pack('<Q', info.offset))
                f.write(struct.pack('<Q', info.size))
                # 写入校验和
                f.write(bytes.fromhex(info.checksum))
            
            # 5. 计算并写入整体校验和
            f.seek(0)
            # 跳过魔数、版本号、文件数量和校验和
            f.seek(12)
            data_for_checksum = f.read()
            final_checksum = self._calculate_checksum(data_for_checksum)
            
            # 写入整体校验和
            f.seek(checksum_pos)
            f.write(bytes.fromhex(final_checksum))

def main():
    """主函数"""
    packer = ResourcePacker()
    
    # 示例：打包resources目录
    src_dir = '../resources'
    output_file = '../dist_resources/resources.bin'
    
    # 确保输出目录存在
    os.makedirs(os.path.dirname(output_file), exist_ok=True)
    
    # 打包文件
    print(f"开始打包目录: {src_dir}")
    packer.pack_directory(src_dir, output_file)
    print(f"打包完成: {output_file}")

if __name__ == '__main__':
    main() 